package es.ugr.beequizz.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import es.ugr.beequizz.bean.IncluirRespuestaBean;
import es.ugr.beequizz.bean.RespuestaBean;
import es.ugr.beequizz.bean.ValidacionBean;
import es.ugr.beequizz.dao.GenericDAO;
import es.ugr.beequizz.dao.RespuestaDAO;
import es.ugr.beequizz.model.Respuesta;
import es.ugr.beequizz.model.Usuario;

@Repository
public class RespuestaDAOImpl extends GenericDAO implements RespuestaDAO {

	// Requete SQL para guardar la pregunta
	private static final String INCLUIR_RESPUESTA_SQL = "INSERT INTO respuesta ( pregunta_id, " +
			" contenido_respuesta, correcta, valida, creador_id) " +
			" VALUES ( :pregunta_id , " +
			" :contenidoRespuesta, :correcta, FALSE, :creadorId)"; 
	
	/*Requete para recuperar las respuestas expecificando la pregunta*/
	private static final String BUSCAR_RESPUESTA_SQL = "SELECT respuesta.id, respuesta.correcta, respuesta.valida, respuesta.contenido_respuesta, usuario.nombre, usuario.apellidos FROM respuesta " +
			"INNER JOIN usuario ON (respuesta.creador_id = usuario.id) " +
			"WHERE pregunta_id = :preguntaId";
	
	/*Requete para suprimir una respuesta*/
	private static final String SUPRIMIR_RESPUESTA_SQL = "DELETE FROM respuesta WHERE id = :respuestaId";
	
	/*Requete para suprimir una respuesta asociada a una pregunta*/
	private static final String SUPRIMIR_RESPUESTA_ID_PREGUNTA_SQL = "DELETE FROM respuesta WHERE pregunta_id = :preguntaIdSuprimir";
	
	/*Requete para recuperar respuestas aleatorias correspondientes a una pregunta en particular*/
	private static final String RECUPERAR_RESPUESTAS_SQL = "SELECT * FROM ((SELECT * FROM respuesta WHERE valida = true AND pregunta_id = :preguntaId AND correcta = true LIMIT :numRespuestasOK)" +
			"UNION (SELECT * FROM respuesta WHERE valida = true AND pregunta_id=:preguntaId AND correcta=false LIMIT :numRespuestasKO))" +
			"AS todasrespuestas ORDER BY random()";
	
	/*Requete para recuperar si la respuesta es correcta o no */
	private static final String VALIDAR_RESPUESTA_SQL = "SELECT correcta FROM respuesta WHERE id = :respuestaId";
	
	/*Demanda SQL para guardar la respuesta a la pregunta proporcionada*/
	private static final String GUARDAR_RESPUESTA_SQL = "INSERT INTO respuesta_pregunta (partida_id, usuario_id, pregunta_id, respuesta_id)"+
					" VALUES (:partidaId, :usuarioId, :preguntaId, :respuestaId) ";

	private static final String RECUPERAR_RESPUESTA_SQL = "SELECT * FROM respuesta WHERE id = :id";

	private static final String MODIFICAR_RESPUESTA_SQL = "UPDATE respuesta SET (contenido_respuesta, correcta, valida) = (:contenidoRespuesta , :correcta, :valida) WHERE id = :id";

	private static final String VALIDACION_RESPUESTA_SQL = " UPDATE respuesta SET valida = :valida WHERE id = :id";
	
	
	public void incluirRespuesta(IncluirRespuestaBean bean) {		
		// Inicializacion de los parametros que vamos a guardar
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("pregunta_id", bean.getPreguntaId());
		params.put("contenidoRespuesta", bean.getContenidoRespuesta());
		params.put("correcta", bean.getCorrecta());
		params.put("creadorId", bean.getCreadorId());
		this.namedTemplate.update(INCLUIR_RESPUESTA_SQL, params);
		
	}
	
	
	private class RespuestaRowMapper implements RowMapper<Respuesta>{
		
		public Respuesta mapRow(ResultSet result, int arg1) throws SQLException {
			
			Respuesta respuesta = new Respuesta();
			respuesta.setId(result.getLong("id"));
			respuesta.setCorrecta(result.getBoolean("correcta"));
			respuesta.setContenidoRespuesta(result.getString("contenido_respuesta"));
			respuesta.setValida(result.getBoolean("valida"));
			
			return respuesta;
		}
		
	}
	
	private class RespuestaUsuarioRowMapper implements RowMapper<Respuesta>{
		
		public Respuesta mapRow(ResultSet result, int arg1) throws SQLException {
			
			Respuesta respuesta = new Respuesta();
			respuesta.setId(result.getLong("id"));
			respuesta.setCorrecta(result.getBoolean("correcta"));
			respuesta.setContenidoRespuesta(result.getString("contenido_respuesta"));
			respuesta.setValida(result.getBoolean("valida"));
			
			Usuario usuario = new Usuario();
			usuario.setApellidos(result.getString("apellidos"));
			usuario.setNombre(result.getString("nombre"));
			respuesta.setCreador(usuario);
			return respuesta;
		}
		
	}
	
	public List<Respuesta> recuperarRespuestas(Long preguntaId){
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("preguntaId", preguntaId);
		return this.namedTemplate.query(BUSCAR_RESPUESTA_SQL, params, new RespuestaUsuarioRowMapper());
	}

	public void suprimirRespuesta(Long id) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("respuestaId", id);
		
		this.namedTemplate.update(SUPRIMIR_RESPUESTA_SQL, params);
	}

	public void suprimirRespuestaIdPregunta(Long id) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("preguntaIdSuprimir", id);
		
		this.namedTemplate.update(SUPRIMIR_RESPUESTA_ID_PREGUNTA_SQL, params);
		
		
	}

	public List<Respuesta> recuperarContenidoRespuestas(int numRespuestasOK,
			int numRespuestasKO, Long preguntaId) {
	
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("preguntaId", preguntaId);
		params.put("numRespuestasOK", numRespuestasOK);
		params.put("numRespuestasKO", numRespuestasKO);
		
		return this.namedTemplate.query(RECUPERAR_RESPUESTAS_SQL, params, new RespuestaRowMapper());
	}

	public boolean validarRespuesta(Long respuestaId) {
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("respuestaId", respuestaId);
		
		return this.namedTemplate.queryForObject(VALIDAR_RESPUESTA_SQL, params, Boolean.class);
	}

	public void guardarRespuestaPartida(Long partidaId, Long usuarioId,
			Long preguntaId, Long respuestaId) {
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("partidaId", partidaId);
		params.put("usuarioId", usuarioId);
		params.put("preguntaId", preguntaId);
		params.put("respuestaId", respuestaId);
		
		namedTemplate.update(GUARDAR_RESPUESTA_SQL, params);
				
		
	}
	
	private class RespuestaBeanRowMapper implements RowMapper<RespuestaBean> {

		public RespuestaBean mapRow(ResultSet result, int arg1) throws SQLException {
			RespuestaBean respuesta = new RespuestaBean();
			respuesta.setId(result.getLong("id"));
			respuesta.setContenidoRespuesta(result.getString("contenido_respuesta"));
			respuesta.setCorrecta(result.getBoolean("correcta"));
			respuesta.setValida(result.getBoolean("valida"));
			
			respuesta.setPreguntaId(result.getLong("pregunta_id"));
			return respuesta;
		}
	}

	public RespuestaBean recuperarRespuesta(Long respuestaId) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", respuestaId);
		return namedTemplate.queryForObject(RECUPERAR_RESPUESTA_SQL, params, new RespuestaBeanRowMapper());
	}

	public void modificarRespuesta(RespuestaBean respuestaBean) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", respuestaBean.getId());
		params.put("contenidoRespuesta", respuestaBean.getContenidoRespuesta());
		params.put("correcta", respuestaBean.getCorrecta());
		params.put("valida", respuestaBean.isValida());
		namedTemplate.update(MODIFICAR_RESPUESTA_SQL, params);
	}

	public void validacionRespuesta(ValidacionBean bean) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", bean.getId());
		params.put("valida", bean.isValido());
		
		this.namedTemplate.update(VALIDACION_RESPUESTA_SQL, params);
	}
	

}
